﻿// -----------------------------------------------------------------------
// <copyright file="Installer.cs" company="JSC Centido">
//  Copyright (c) JSC Centido. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------

using System;

namespace Centido.Core
{
    /// <summary>
    ///   A generic metadata installer.
    /// </summary>
    public abstract class Installer
    {
        /// <summary>
        /// The database connection string.
        /// </summary>
        private string _dbConnectionString = string.Empty;
        /// <summary>
        /// The database provider name.
        /// </summary>
        private string _dbProviderName = string.Empty;

        /// <summary>
        ///   Initializes a new instance of the class <see cref="Centido.Core.Installer"/> class.
        /// </summary>
        protected Installer()
        {
            
        }

        /// <summary>
        ///   Initializes a new instance of the <see cref="Centido.Core.Installer"/> class.
        /// </summary>
        /// <param name="dbConnectionString">The connection string.</param>
        /// <param name="dbProviderName">The database provider invariant name.</param>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="dbConnectionString"/> is null.</exception>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="dbProviderName"/> is null.</exception>
        /// <exception cref="ArgumentException">Thrown when the value of <paramref name="dbConnectionString"/> is an empty string.</exception>
        /// <exception cref="ArgumentException">Thrown when the value of <paramref name="dbProviderName"/> is an empty string.</exception>
        protected Installer(string dbConnectionString, string dbProviderName)
        {
            if (dbConnectionString == null)
                throw new ArgumentNullException("dbConnectionString");
            if (dbProviderName == null)
                throw new ArgumentNullException("dbProviderName");
            if (dbConnectionString.Trim().Length == 0)
                throw new ArgumentException("The connection string cannot be empty.");
            if (dbProviderName.Trim().Length == 0)
                throw new ArgumentException("The database provider name cannot be empty.");

            DbConnectionString = dbConnectionString.Trim();
            DbProviderName = dbProviderName.Trim();
        }

        /// <summary>
        /// Gets the connection string.
        /// </summary>
        public string DbConnectionString
        {
            get { return _dbConnectionString; }
            set
            {
                if (value == null)
                    throw new ArgumentNullException("value");
                if (value.Trim().Length == 0)
                    throw new ArgumentException("The database connection string cannot be empty.");

                _dbConnectionString = value.Trim();
            }
        }

        /// <summary>
        /// Gets the database provider invariant name.
        /// </summary>
        public string DbProviderName
        {
            get { return _dbProviderName; }
            set
            {
                if (value == null)
                    throw new ArgumentNullException("value");
                if (value.Trim().Length == 0)
                    throw new ArgumentException("The database provider name cannot be empty.");

                _dbProviderName = value.Trim();
            }
        }

        /// <summary>
        ///   Gets the database product name.
        /// </summary>
        public abstract string ProductName { get; }

        /// <summary>
        ///   Gets the version of the metadata schema.
        /// </summary>
        public abstract int SchemaVersion { get; }

        /// <summary>
        ///   Gets the version of the metadata logic.
        /// </summary>
        public abstract int LogicVersion { get; }

        /// <summary>
        ///   Installs the metadata schema.
        /// </summary>
        /// <returns>Returns the current installer.</returns>
        public abstract Installer InstallSchema();

        /// <summary>
        ///   Installs the metadata logic.
        /// </summary>
        /// <returns>Returns the current installer.</returns>
        public abstract Installer InstallLogic();

        /// <summary>
        ///   Creates an application user.
        /// </summary>
        /// <param name = "userName">The application user name.</param>
        /// <param name="userPassword">The application user password.</param>
        /// <param name="dbName">The application user database name.</param>
        /// <returns>Returns the current installer.</returns>
        public abstract Installer CreateAppUser(string userName, string userPassword, string dbName);

        /// <summary>
        ///   Retrieves the application user installation script.
        /// </summary>
        /// <param name="userName">The application user name.</param>
        /// <param name="userPassword">The application user password.</param>
        /// <param name="dbName">The application user database name.</param>
        /// <returns>Returns the application user installation script.</returns>
        public abstract string GetAppUserInstallationScript(string userName, string userPassword, string dbName);

        /// <summary>
        ///   Installs the metadata.
        /// </summary>
        /// <returns>Returns the current installer.</returns>
        public Installer Install()
        {
            Uninstall();

            InstallSchema();

            return InstallLogic();
        }

        /// <summary>
        ///   Uninstalls the metadata.
        /// </summary>
        /// <returns>Returns the current installer.</returns>
        public abstract Installer Uninstall();
    }
}